
#include <BStyle>
#include <BEntry>
#include <BFolder>
#include <BSystem>
#include <BGridLayout>
#include <BHBoxLayout>
#include <BVBoxLayout>
#include <BApplication>

#include "ToolButton.h"
#include "MainWindow.h"

MainWindow::MainWindow(BWidget* parent) : BMainWindow(parent)
{
	_strikingItem = 0;

	BHBoxLayout* hlayout00 = new BHBoxLayout();
	{
		_languageComboBox = new BComboBox();
		_searchComboBox = new BComboBox();
		_searchComboBox->setEditable(true);
		_searchButton = new BButton("search");
		_searchButton->setName("search");
		_searchButton->setForm(Form_IconAlone);
		hlayout00->addWidget(_languageComboBox, 0);
		hlayout00->addWidget(_searchComboBox);
		hlayout00->addWidget(_searchButton, 0);
	}

	_htmlTreeWidget = new BTreeWidget();

	BHBoxLayout* hlayout01 = new BHBoxLayout();
	{
		_prevButton = new BButton(Graph_Arrow_Left_Fill);
		_prevButton->setForm(Form_IconAlone);
		_prevButton->setWidthPolicy(Policy_Preferred);

		_nextButton = new BButton(Graph_Arrow_Right_Fill);
		_nextButton->setForm(Form_IconAlone);
		_nextButton->setWidthPolicy(Policy_Preferred);

		_aboveButton = new BButton(Graph_Arrow_Up_Fill);
		_aboveButton->setForm(Form_IconAlone);
		_aboveButton->setWidthPolicy(Policy_Preferred);

		_pathComboBox = new BComboBox();

		hlayout01->addWidget(_prevButton);
		hlayout01->addWidget(_nextButton);
		hlayout01->addWidget(_aboveButton);
		hlayout01->addWidget(_pathComboBox);
	}

	_htmlWidget = new BHtmlWidget();

	BGridLayout* gridLayout = new BGridLayout(this);
	gridLayout->setRowSpacing(5);
	gridLayout->setColumnSpacing(5);
	gridLayout->setSplitable(true);
	gridLayout->setRowPolicy(0, Policy_Preferred);
	gridLayout->setColumnStretch(0, 1);
	gridLayout->setColumnStretch(1, 20);
	gridLayout->setSplitable(true);
	gridLayout->addLayout(0, 0, hlayout00);
	gridLayout->addLayout(0, 1, hlayout01);
	gridLayout->addWidget(1, 0, _htmlTreeWidget);
	gridLayout->addWidget(1, 1, _htmlWidget);

	connect(_languageComboBox, Signal_CurrentChanged, &MainWindow::slotLanguageCurrentChanged);
	connect(_searchComboBox, Signal_EditFinished, &MainWindow::slotSearchEditFinished);
	connect(_searchButton, Signal_Clicked, &MainWindow::slotSearchButtonClicked);
	connect(_htmlTreeWidget, Signal_ItemDoubleClicked, &MainWindow::slotItemDoubleClicked);
	connect(_htmlWidget, Signal_ItemSelected, &MainWindow::slotHtmlItemSelected);
	connect(_htmlWidget, Signal_ItemClicked, &MainWindow::slotHtmlItemClicked);
	connect(_htmlWidget, Signal_Framed, &MainWindow::slotHtmlWidgetFramed);

	BFolder folder("../../manual");
	if (folder.open())
	{
		for (int i = 0; i < folder.entryCount(); i++)
		{
			BEntry* entry = folder.entry(i);
			if (entry->attrib() & Attrib_Folder)
			{
				_languageComboBox->addItem(entry->name());
			}
		}
	}
	_config = new Config();
	_config->setName("data/config/assistant.xml");
	_config->load();
	_languageComboBox->setText(_config->language());
}
MainWindow::~MainWindow()
{
	if (_config->isDirty())
	{
		_config->save();
	}
}

void MainWindow::openHtmlPage(const BString& fileName)
{
	_htmlWidget->load(fileName);
	_htmlWidget->scrollTo(Part_LeftTop);
	_strikingItem = 0;
}

BTreeItem* MainWindow::createTreeItem(BEntry* entry)
{
	if (entry->attrib() & Attrib_Folder)
	{
		BFolder folder(entry->path());
		if (folder.open())
		{
			for (int i = 0; i < folder.entryCount(); i++)
			{
				BEntry* entry = folder.entry(i);
				if (entry->name().endWith(".html"))
					continue;
				folder.removeEntry(i--);
			}
		}
		if (folder.entryCount() > 0)
		{
			BTreeItem* item = new BTreeItem(entry->name());
			for (int i = 0; i < folder.entryCount(); i++)
			{
				BEntry* subEntry = folder.entry(i);
				BTreeItem* childItem = createTreeItem(subEntry);
				item->addChild(childItem);
			}
			item->setAsset(entry);
			return item;
		}
		return 0;
	}
	BString name = entry->name();
	name -= name.dext();
	BTreeItem* item = new BTreeItem(name);
	item->setAsset(entry);
	return item;
}
void MainWindow::freshItemIcon(BTreeItem* item)
{
	BEntry* entry = item->asset();
	const BStyle* style = this->realStyle();
	BIcon* icon = style->icon(entry->path().ext());
	if (!icon)
		icon = BSystem::EntryIcon(entry->path());
	item->setIcon(icon);
	for (int i = 0; i < item->childCount(); i++)
	{
		BTreeItem* child = item->child(i);
		freshItemIcon(child);
	}
}
void MainWindow::searchTreeItem(BTreeItem* item)
{
	if (item->enabled())
	{
		if (BEntry* entry = item->asset())
		{
			if (item->property("document").empty())
			{

			}
			BXmlNode* xml = item->property("document");
			for (int i = 0; i < xml->childCount(); i++)
			{
				searchHtmlItem(dynamic_cast<BHtmlItem*>(xml->child(i)));
			}
		}
	}
}
void MainWindow::searchHtmlItem(BHtmlItem* item)
{
	if (item->name().contain(_searchComboBox->text()))
	{
		_searchListWidget->addItem(item->name())->setAsset(item);
	}
}

void MainWindow::slotLanguageCurrentChanged(BObject* object, const BValue& value)
{
	BComboItem* item = value;
	const BString& language = item->text();
	_config->setLanguage(language);
	BString path("../../manual/");
	BFolder folder(path + language);
	if (folder.open())
	{
		_htmlTreeWidget->clearItems();
		for (int i = 0; i < folder.entryCount(); i++)
		{
			BEntry* entry = folder.entry(i);
			if (BTreeItem* item = createTreeItem(entry))
			{
				_htmlTreeWidget->addItem(item);
				freshItemIcon(item);
			}
		}
		_htmlWidget->clearItems();
		if (_htmlWidget->fileName().size())
		{
			BString fileName = _htmlWidget->fileName().name();
			if (BTreeItem* item = _htmlTreeWidget->locate(fileName))
			{
				BEntry* entry = item->asset();
				openHtmlPage(entry->path());
			}
		}
		if (_htmlWidget->empty())
		{
			openHtmlPage(path + language + "/index.html");
		}
	}
}
void MainWindow::slotSearchEditFinished(BObject* object, const BValue& value)
{
	_searchingItem = _htmlTreeWidget->item(0);
}
void MainWindow::slotSearchButtonClicked(BObject* object, const BValue& value)
{

}
void MainWindow::slotItemDoubleClicked(BObject* object, const BValue& value)
{
	if (BTreeItem* item = value)
	{
		BEntry* entry = item->asset();
		const BString& path = entry->path();
		if (path.endWith(".html"))
		{
			openHtmlPage(path);
		}
	}
}
void MainWindow::slotHtmlItemSelected(BObject* object, const BValue& value)
{
	_selectTick = bTime();
	_strikingItem = value;
}
void MainWindow::slotHtmlItemClicked(BHtmlWidget* htmlWidget, const BValue& value)
{
	if (htmlWidget->editable())
		return;
	BHtmlItem* item = value;
	if (item && item->name() == 'a')
	{
		const BString& name = htmlWidget->fileName();
		const BString& href = item->attrib("href");
		if (!href.beginWith('#'))
		{
			BString fileName = name.path();
			fileName << '/' << href;
			openHtmlPage(fileName);
		}
	}
}
void MainWindow::slotHtmlWidgetFramed(BObject* object, const BValue& value)
{
	if (_strikingItem)
	{
		BPainter painter(_htmlWidget);
		BByte alpha = BByte((1 - ((bTime() - _selectTick) / 1)) * 255);
		if (alpha)
		{
			BColor color = painter.color(Color_Border, State_Checked);
			color.a() = alpha;
			BRect itemRect = _strikingItem->rect();
			painter.setColor(color);
			painter.drawRect(itemRect);
		}
	}
}

void MainWindow::updateEvent(const BEvent& event)
{
	BReal now = event.time();
	if (_strikingItem)
	{
		if (now - _selectTick > 1)
			_strikingItem = 0;
		_htmlWidget->fresh();
	}
	BReal interval = 1 / BApplication::frequency();
	if (_searchingItem)
	{
		const BString& text = _searchComboBox->text();
		while (_searchingItem && bTime() - now < interval)
		{
			searchTreeItem(_searchingItem);
			_searchingItem = _searchingItem->next();
		}

	}
}
void MainWindow::styleEvent(const BEvent& event)
{
	BMainWindow::styleEvent(event);
	const BStyle* style = event.value();
	for (int i = 0; i < _htmlTreeWidget->itemCount(); i++)
	{
		BTreeItem* item = _htmlTreeWidget->item(i);
		freshItemIcon(item);
	}
}
